/* Copyright 2011 Rok Lenarčič 
 * 
 * This file is a part of MicroFn.
 * 
 * MicroFn is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * MicroFn is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/> */

package net.rlenar.microfn.func;

import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;

import net.rlenar.microfn.IFn;

public class FnStringComparator<E> extends FnComparator<E> {
	private Collator collator = null;
    public FnStringComparator(IFn fn, boolean ascending, Locale locale, boolean caseSensitive) {
    	super(fn, ascending);
        this.collator = Collator.getInstance(locale);
        if (caseSensitive) {
        	collator.setStrength(Collator.TERTIARY);
        } else {
        	collator.setStrength(Collator.SECONDARY);
        }    	
    }
    public FnStringComparator(IFn fn, boolean ascending, NullStrategy nullElementStrategy, Locale locale, boolean caseSensitive) {
    	super(fn, ascending, nullElementStrategy);
        this.collator = Collator.getInstance(locale);
        if (caseSensitive) {
        	collator.setStrength(Collator.TERTIARY);
        } else {
        	collator.setStrength(Collator.SECONDARY);
        }      	
    }
    public FnStringComparator(IFn fn, boolean ascending, NullStrategy nullElementStrategy, Comparator<E> secondary, Locale locale, boolean caseSensitive) {
    	super(fn, ascending, nullElementStrategy, secondary);
        this.collator = Collator.getInstance(locale);
        if (caseSensitive) {
        	collator.setStrength(Collator.TERTIARY);
        } else {
        	collator.setStrength(Collator.SECONDARY);
        }      	
    }    
    protected FnStringComparator() {
    	
    }
    /**
     * Returns new comparator which asymetrically treats compare arguments. The first argument of every compare
     * is used as-is and function is applied only on the second argument.
     * 
     * @return
     */
    public FnComparator<E> getAsymmetricComparator() {
    	FnStringComparator<E> comp = new FnStringComparator<E>();
    	comp.asymmetric = true;
    	comp.collator = collator;
    	comp.direction = direction;
    	comp.fn = fn;
    	comp.elementStrategy = elementStrategy;
    	comp.secondary = secondary;
    	return comp;
    }
	public int compare(E o1, E o2) {
        Object result1 = fn.invoke(o1);
        Object result2 = asymmetric ? o2 : fn.invoke(o2);
        int result;
        if (result1 == null) {
            if (result2 == null) {
            	if (secondary == null) {
            		return 0;
            	} else {
            		return secondary.compare(o1, o2);
            	}
            } else {
                return elementStrategy.getReturnForFirstElNull(direction);
            }
        } else if (result2 == null) {
            return elementStrategy.getReturnForFirstElNull(direction) * -1;
        } else {
        	if (secondary == null) {
        		return collator.compare(result1, result2) * direction;	
        	} else {
        		result = collator.compare(result1, result2) * direction;
        		return result == 0 ? secondary.compare(o1, o2) : result;
        	}            
        }		
	}    
}
